package com.yelink.metrics.core.service;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yelink.metrics.core.domain.BaseMetricsEntity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.ParameterizedType;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Service
 *
 * @author shiqidi
 */
public abstract class BaseMetricsServiceImpl<M extends BaseMapper<T>, T extends BaseMetricsEntity> extends ServiceImpl<M, T> implements BaseMetricsService<T> {


    @Value("${metrics-sdk.db:dfs_metrics}")
    private String db;

    /**
     * model真正的类型，lambdaQuery的时候需要传进去，不然报异常 can not find lambda cache for this entity
     */
    private final Class<T> clazz;

    @SuppressWarnings("unchecked")
    public BaseMetricsServiceImpl() {
        ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass();
        clazz = (Class<T>) type.getActualTypeArguments()[1];
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateBatchByUnique(List<T> results) {
//        DynamicDbHolder.setDb(db);
        Date now = new Date();
        Map<String, T> resultMap = results.stream().peek(e -> e.setTime(now)).collect(Collectors.toMap(T::getUniCode, Function.identity()));

        List<T> oldResults = this.list(Wrappers.lambdaQuery(clazz)
                .in(BaseMetricsEntity::getUniCode, resultMap.keySet())
        );
        if(CollUtil.isNotEmpty(oldResults)) {
            oldResults.forEach(oldResult -> {
                T newResult = resultMap.get(oldResult.getUniCode());
                if(newResult != null) {
                    newResult.setId(oldResult.getId());
                }
            });
        }
        this.saveOrUpdateBatch(results);
//        DynamicDbHolder.clear();
    }

    @Override
    public String getTargetName() {
        TableName tableName = clazz.getAnnotation(TableName.class);
        return Optional.ofNullable(tableName).map(TableName::value).orElse(null);
    }
}
